const Str = require("../util/StringUtil") ,
    moment = require("moment") ,
    LocalCache = require("node-cache") 

const CacheType = {
    Local : "local" ,
    Redis : "remote" ,
    Db : "db"
}

class CacheEntity{

    constructor( obj ){
        this.key = obj.key 
        this.type = obj.type || CacheType.Local 
        this.expire = obj.expire || -1  //默认不失效
    }

    static to( key , type , expire ){
        return new CacheEntity({
            key : key ,
            type : type ,
            expire : expire 
        })
    }

    /**
     *  格式化参数
     * @param {*} ps
     *      uid 
     *      date
     *      time
     *      datetime
     */
    format( key , ps ){
        let kv = {}
        Object.assign( kv ,ps.pag , ps.ps , ps.auth )
        kv["date"] = moment().format("YYYYMMDD")
        kv["time"] = moment().format("HHmm")
        kv["datetime"] = moment().format("YYYYMMDDHHmm")
        return Str.format(key , kv)
    }

    trueKey( ps ){
        if( ps )
            return this.format( this.key , ps )
        else
            return this.key 
    }

}

class RequestCache{

    constructor(){
        this.localCache = new LocalCache()
    }

    getRedisClient( ){
        return global._SERVICE.redis
    }

    getCache( ctx ){
        const uri = ctx.request.method.toUpperCase() + " " + ctx.request.path 
        try{
            return ctx.app._Router[ uri ].cached
        }catch(e){
            return null 
        }
    }

    cached( ctx , ps , result ){
        //uri
        const entity = this.getCache( ctx )
        if( entity ){
            const key = entity.trueKey( ps )
            const cacheType = entity.type 
            if( cacheType == CacheType.Local ){
                this.localCache.set( key , result , entity.expire )
            }else if( cacheType == CacheType.Redis ){
                this.getRedisClient().setAsync( key , result , entity.expire )
            }
        }
    }

    async value( ctx , ps ){
        const entity = this.getCache( ctx )
        if( entity ){
            const key = entity.trueKey( ps )
            const cacheType = entity.type 
            if( cacheType == CacheType.Local ){
                return this.localCache.get( key )
            }else if( cacheType == CacheType.Redis ){
                return await this.getRedisClient().getAsync( key )
            }
        }
        
        return null 
    }

    isNeedCached( ctx ){
        return this.getCache( ctx ) ? true : false 
    }

}

module.exports = {
    RequestCache , CacheType , CacheEntity
}